<script setup>
import { ControlButton, Controls } from '@vue-flow/controls';
import { useVueFlow } from '@vue-flow/core';
import MonacoEditor from 'monaco-editor-vue3';
import { defineEmits, defineExpose } from 'vue';
import { VsNotification } from 'vuesax-alpha';
import { useLayout } from '../debug/useLayout';
import ArrowIcon from '../icon/ArrowIcon.vue';
import ControlsIcon from '../icon/ControlsIcon.vue';

const props = defineProps({
  processPanelShow: {
    type: Boolean,
    required: true,
  },
})

const emit = defineEmits(['updateInteractionControls','removeNodesEdges','debugMode','layoutGraph'])
const { graph, layout, previousDirection } = useLayout()

const { 
  setViewport, 
  toObject,
  fromObject,
  updateNodeData,
  getNodes,
  getEdges,
  removeEdges,
  removeNodes,
  fitView
} = useVueFlow()

const el = ref('')
const format = ref(false)
const interactionControls = ref(false)
const resCode = ref(0)
const flowIndex = ref(0)
const flowKey = 'ivy-flow-0'

const getParams = () => {
  const data = toObject()

  data.format = format.value
  
  return data
}

const processPanelShow = ref(props.processPanelShow || false)
const clean = () =>{
  emit('removeNodesEdges', {})
  processPanelShow.value = false
  emit('debugMode', {processPanelShow: processPanelShow.value})

  setViewport({ x: 0, y: 0, zoom: 1 })
}

const debugModeClick = (val) =>{
  processPanelShow.value = val
  emit('debugMode', {processPanelShow: processPanelShow.value})
}

const toEL = async () => {
  const res = await $ivyApi.post('/liteflow/parser/jsonToEL', getParams())
  resCode.value = res.code
  if(res.code == 500){
    el.value = res.message
  }else{
    el.value = res.data
  }
}

const popupFlowEL = ref(false)
const elStr = ref('THEN(a,b,c)')
const elToJsonStr = ref('')
const elToJson = () => {
  popupFlowEL.value = true
  elToJsonStr.value = ''
}
const elToJsonClick = async () => {
  const res = await $ivyApi.post('/liteflow/parser/elToJson', {el: elStr.value})
  elToJsonStr.value = res.data;
}
const jsonToFlowLayoutGraph = ref(true)
const jsonToFlowClick = () => {
  fromObject(JSON.parse(elToJsonStr.value))
  if(jsonToFlowLayoutGraph.value){
    emit('layoutGraph', 'LR')
  }
}

function updatePos() {
  // for (const node of getNodes.value) {
  //   node.position = {
  //     x: Math.random() * 400,
  //     y: Math.random() * 400,
  //   }
  // }
}


function resetTransform() {
  setViewport({ x: 0, y: 0, zoom: 1 })
}

watch(interactionControls, val => {  
  emit('updateInteractionControls', val)
})

function onSave() {
  localStorage.setItem(flowKey, JSON.stringify(toObject()))
}

function onRestore() {
  const flow = JSON.parse(localStorage.getItem(flowKey))

  if (flow) {
    fromObject(flow)
  }
}

const popupFlowJson = ref(false)
const flowJson = ref('')

const onJson = () => {
  flowJson.value = JSON.stringify(toObject(), null, 2)
  popupFlowJson.value = true
}

const copyFlowJson = () => {
  navigator.clipboard.writeText(flowJson.value).then(() => {
    openSuccessNotification(null,'内容已复制到剪贴板!')
  }).catch((error) => {
    openErrorNotification('复制失败')
    console.error('复制失败：', error);
  });
}


const onFilterJson = (type) => {
  const flowData = toObject()
  if(type == 0){
    flowJson.value = JSON.stringify(flowData, null, 2)
  }else if(type == 1){
    const filterNodes = flowData.nodes.map(node => {
      const { position, data, initialized,targetPosition,sourcePosition, ...rest } = node;
      const { style, mode,isRunning,isFinished,hasError,isSkipped,isCancelled, ...dataRest } = data;
      return { ...rest, data: dataRest };
    });
    const filterEdges = flowData.edges.map(node => {
      const { data, showToolbar, sourceHandle, targetHandle, updatable, animated, markerEnd, sourceX, sourceY, targetX, targetY, ...rest } = node;
      const { style, ...dataRest } = data;
      return { ...rest, data: dataRest };
    });
    flowJson.value = JSON.stringify({nodes: filterNodes, edges: filterEdges}, null, 2)
  }else if(type == 2){
    // 过滤出不需要的属性
    const filters = flowData.nodes.map(node => {
      const { position, data, initialized,targetPosition,sourcePosition, ...rest } = node;
      const { style, mode,isRunning,isFinished,hasError,isSkipped,isCancelled, ...dataRest } = data;
      return { ...rest, data: dataRest };
    });
    flowJson.value = JSON.stringify(filters, null, 2)
  }else if(type == 3){
    // 过滤出不需要的属性
    const filters = flowData.edges.map(node => {
      const { data, showToolbar, sourceHandle, targetHandle, updatable, animated, markerEnd, sourceX, sourceY, targetX, targetY, ...rest } = node;
      const { style, ...dataRest } = data;
      return { ...rest, data: dataRest };
    });
    flowJson.value = JSON.stringify(filters, null, 2)
  }
}

const popupSetting = ref(false)
const activeSetting = ref()
const onSetting = () => {
  popupSetting.value = true
}

async function layoutGraph(direction) {
  emit('layoutGraph', direction)
  // getNodes.value = layout(getNodes.value, getEdges.value, direction)
  // nextTick(() => {
  //   fitView()
  // })
}

const nodeMode = (mode) => {
  for (const node of getNodes.value) {
    node.data.mode = mode
  }
}


//编辑器
const options = ref({
  colorDecorators: true,
  lineHeight: 24,
  tabSize: 2,
})

const editorDidMount = (editor) => {
  console.log(editor);
  // editor.onDidScrollChange((e) => {
  //   console.log(e);
  // });
}

const copyEL = () => {
  navigator.clipboard.writeText(el.value).then(() => {
    openSuccessNotification(null,'内容已复制到剪贴板!')
  }).catch((error) => {
    openErrorNotification('复制失败')
    console.error('复制失败：', error);
  });
}

//格式化EL表达式
const formatEL = () => {
  format.value = true
  toEL()
}


const openSuccessNotification = (title, content) => {
  VsNotification({
    position: 'top-center',
    shape: 'square',
    sticky: true,
    width: 'auto',
    title: title,
    color: "success",
    content: content
  })
}

const openErrorNotification = (title, content) => {
  VsNotification({
    position: 'top-center',
    shape: 'square',
    sticky: true,
    width: 'auto',
    title: title,
    color: 'danger',
    content: content
  })
}

// 提供调用方法
defineExpose({
  toEL,
})
</script>

<template>
  <Controls position="top-right">
    <vs-tooltip placement="left" trigger="click">
      <ControlButton>
        <ControlsIcon name="layout" />
      </ControlButton>
      <template #content> 节点布局
        <div class="layout-panel">
          <button title="LR布局" @click="layoutGraph('LR')">
            <ArrowIcon name="arrowRight" />
          </button>

          <button title="TB布局" @click="layoutGraph('TB')">
            <ArrowIcon name="arrowDown" />
          </button>

          <button title="RL布局" @click="layoutGraph('RL')">
            <ArrowIcon name="arrowLeft" />
          </button>

          <button title="BT布局" @click="layoutGraph('BT')">
            <ArrowIcon name="arrowUp" />
          </button>

        </div>
      </template>
    </vs-tooltip>

    <vs-tooltip placement="left" trigger="click">
      <ControlButton>
        <ControlsIcon name="components" />
      </ControlButton>
      <template #content> 节点模式
        <div class="layout-panel">
          <button title="默认模式" @click="nodeMode('default')">
            默认模式
          </button>
          <button title="简单模式" @click="nodeMode('simple')">
            简单模式
          </button>
        </div>
      </template>
    </vs-tooltip>

    <vs-tooltip placement="left">
      <ControlButton @click="resetTransform">
        <ControlsIcon name="refresh" />
      </ControlButton>
      <template #content> 重置缩放和平移 </template>
    </vs-tooltip>

    <vs-tooltip placement="left">
      <ControlButton @click="clean">
        <ControlsIcon name="trash" />
      </ControlButton>
      <template #content> 清空 </template>
    </vs-tooltip>

    <vs-tooltip placement="left">
      <ControlButton @click="interactionControls = !interactionControls">
        <ControlsIcon
          v-if="interactionControls"
          name="adjustmentsOn"
        />
        <ControlsIcon
          v-else
          name="adjustmentsOff"
        />
      </ControlButton>
      <template #content> {{interactionControls ? '显示交互控件' : '隐藏交互控件'}} </template>
    </vs-tooltip>

    <vs-tooltip placement="left">
      <ControlButton @click="onSave">
        <ControlsIcon name="save" />
      </ControlButton>
      <template #content> 保存 </template>
    </vs-tooltip>

    <vs-tooltip placement="left">
      <ControlButton @click="onRestore">
        <ControlsIcon name="restore" />
      </ControlButton>
      <template #content> 还原 </template>
    </vs-tooltip>

    <vs-tooltip placement="left">
      <ControlButton @click="format = !format">
        <ControlsIcon
          v-if="format"
          name="format"
        />
        <ControlsIcon
          v-else
          name="noFormat"
        />
      </ControlButton>
      <template #content> {{format ? '启用格式化EL表达式' : '禁用格式化EL表达式'}} </template>
    </vs-tooltip>

    <vs-tooltip placement="left">
      <ControlButton @click="toEL">
        <ControlsIcon name="log" />
      </ControlButton>
      <template #content> JSON转EL </template>
    </vs-tooltip>

    <vs-tooltip placement="left">
      <ControlButton @click="elToJson">
        <ControlsIcon name="json" />
      </ControlButton>
      <template #content> EL转JSON </template>
    </vs-tooltip>

    <vs-tooltip placement="left">
      <ControlButton @click="onJson">
        <ControlsIcon name="code" />
      </ControlButton>
      <template #content> 流程数据 </template>
    </vs-tooltip>

    <vs-tooltip placement="left">
      <ControlButton v-if="processPanelShow" @click="debugModeClick(false)">
        <ControlsIcon name="bug" />
      </ControlButton>
      <ControlButton v-else @click="debugModeClick(true)">
        <ControlsIcon name="bugOff" />
      </ControlButton>
      <template #content> 调试模式 </template>
    </vs-tooltip>

    <vs-tooltip placement="left">
      <ControlButton @click="onSetting">
        <ControlsIcon name="setting" />
      </ControlButton>
      <template #content> 设置 </template>
    </vs-tooltip>
  </Controls>

  <vs-dialog v-model="popupFlowJson"  not-close auto-width>
    <template #header>
      <h3>流程数据</h3>
    </template>
    <div class="con-content-scroll">
      <vs-row style="margin-block-end: 8px;">
        <vs-button class="ivy-btn-mr-8" type="floating" size="small" @click="onFilterJson(0)"> 原始数据 </vs-button>
        <vs-button class="ivy-btn-mr-8" type="floating" size="small" @click="onFilterJson(1)"> 简单数据 </vs-button>
        <vs-button class="ivy-btn-mr-8" type="floating" size="small" @click="onFilterJson(2)"> 节点数据 </vs-button>
        <vs-button class="ivy-btn-mr-8" type="floating" size="small" @click="onFilterJson(3)"> 路径数据 </vs-button>
        <vs-button class="ivy-btn-mr-8" type="floating" size="small" @click="copyFlowJson"> 复制 </vs-button>
      </vs-row>
      <MonacoEditor
          theme="vs"
          :options="options"
          language="json"
          :width="700"
          :height="500"
          v-model:value="flowJson"
          >
      </MonacoEditor>
    </div>
  </vs-dialog>

  <vs-dialog v-model="popupFlowEL"  not-close auto-width>
    <template #header>
      <h3>EL转JSON</h3>
    </template>
    <div class="con-content-scroll">
      <vs-row>
        <vs-col :sm="8">
          <vs-input
            v-model="elStr"
            class="w-100 nodrag"
            color="success" 
            label="EL表达式" 
            label-float 
            shape="square"
          />
        </vs-col>
        <vs-col :sm="2">
          <vs-button type="flat" shape="square" @click="elToJsonClick" style="inline-size: 99%;margin-block-start: 24px;">生成JSON</vs-button>
        </vs-col>
        <vs-col :sm="2">
          <vs-button type="flat" shape="square" @click="jsonToFlowClick" style="inline-size: 99%;margin-block-start: 24px;">导入流程</vs-button>
        </vs-col>
      </vs-row>
      <vs-row>
        <div style="margin-block-start: 10px;">
          <vs-switch v-model="jsonToFlowLayoutGraph">
            <template #off> 原样导入流程 </template>
            <template #on> 导入流程时重新排列 </template>
          </vs-switch>
        </div>
      </vs-row>
      <vs-row>
        <vs-divider>流程数据</vs-divider>
        <MonacoEditor
            theme="vs"
            :options="options"
            language="json"
            :width="768"
            :height="360"
            v-model:value="elToJsonStr"
            >
        </MonacoEditor>
      </vs-row>
    </div>
  </vs-dialog>

  <vs-dialog v-model="popupSetting" shape="square" style="min-block-size: 500px;min-inline-size: 800px;">
    <template #header>
      <h3>设置</h3>
    </template>
    <div class="con-content-scroll">
      <vs-tabs alignment="left">
        <vs-tab label="全局设置">
          <div>
            <vs-tabs position="left">
              <vs-tab label="节点设置">
                <div>
                  <vs-switch v-model="active3">
                    <template #off> 默认模式 </template>
                    <template #on> 简单模式 </template>
                  </vs-switch>
                </div>
              </vs-tab>
              <vs-tab label="连线设置">
                <div>
                  
                </div>
              </vs-tab>
            </vs-tabs>
          </div>
        </vs-tab>
      </vs-tabs>
    </div>
  </vs-dialog>

  <div class="ivy-el-div" v-if="el">
    <vs-tooltip placement="top" trigger="click" color="#7d33ff00">
      <span  class="ivy-el-span"
        v-on:hover="handleHover"
        :class="resCode === 200 ? 'ivy-el-span-bg-success' : (resCode === 500 ? 'ivy-el-span-bg-error' : 'ivy-el-span-bg')"
      >
        <!-- <span @click="el = ''" style="position: absolute;cursor: pointer;inset-block-start: -16px;inset-inline-end: -3px;">
          <ControlsIcon name="close" />
        </span> -->
        <pre>{{ el }}</pre>
      </span>
      
      <template #content>
        <div class="layout-panel">
          <vs-button type="relief" size="small" @click="formatEL">格式化</vs-button>
          <vs-button type="relief" size="small" @click="copyEL">复制</vs-button>
          <vs-button type="relief" size="small" @click="el = ''">关闭</vs-button>
        </div>
      </template>
    </vs-tooltip>
  </div>


</template>

<style>

.ivy-el-span{
  position: absolute;
  z-index: 4;
  display: inline-block;
  padding: 8px;
  border-end-end-radius: 6px;
  border-start-end-radius: 6px;
  font-size: 16px;
  inset-block-end: 0;
  max-inline-size: 85%;
  word-break: break-all;
}

.ivy-el-span pre{
  white-space: pre-wrap;
}

.ivy-el-span-bg{
  background-color: transparent;
}

.ivy-el-span-bg-default{
  background-color: #d3d3d3;
}

.ivy-el-span-bg-success{
  background-color: #28c76f;
  color: #fff;
}

.ivy-el-span-bg-error{
  background-color: #ff4757;
  color: #fff
}

.ivy-btn-mr-8{
  margin-inline-end: 8px;
}
</style>
